perm filename SUPDUP.MID[NET,MRC]1 blob sn#302803 filedate 1977-08-28 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00037 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00004 00002	Assembly options, etc.
C00007 00003	AC's, I/O channels, macros
C00009 00004	SUPDUP documentation
C00012 00005	 SUPDUP FEATURES:
C00015 00006	Mappings between ITS and SAIL ASCII
C00018 00007	Data area
C00021 00008	Display crufties
C00024 00009	 More display data stuff
C00026 00010	ITS TTY definitions
C00030 00011	ITS output buffer codes
C00032 00012	Interrupt and UUO service
C00036 00013	Startup, etc.
C00039 00014	Monitor command processor
C00041 00015	Get host name
C00044 00016	ICP ICP ICP
C00047 00017	 (continued from previous page)
C00050 00018	Final pre-display initialization
C00052 00019	Slurp up and send terminal ID
C00054 00020	 Now check to see if we have a reasonable match
C00057 00021	Main program loop, clock interrupt
C00059 00022	TTY input service
C00061 00023	 Output a character to the network buffer in the hairy way
C00064 00024	 More output mapping stuff
C00068 00025	Network input service
C00072 00026	 Subroutines for network input service
C00075 00027	Display hacking
C00078 00028	Display subroutines
C00082 00029	 Non-insert/delete display subroutines
C00086 00030	 Line insert/delete
C00089 00031	 Character insert
C00092 00032	 Character delete
C00094 00033	Display update subroutines
C00097 00034	 More display updating stuff
C00099 00035	SUPDUP commands
C00102 00036	 More SUPDUP commands stuff
C00105 00037	Random routines, literals, etc.
C00108 ENDMK
C⊗;
subttl Assembly options, etc.

title SUPDUP User for Data Discs

; Mark Crispin, SU-AI, August 1977

;  This is the SAIL implementation of the ITS SUPDUP program, which
; is used for display communication across ITS systems.

if1 .insrt MACROS[1,MRC]

nd. icpskt==137				; new SUPDUP ICP socket
nd. pdllen==50				; length of pushdown stack
nd. nlines==38.				; number of lines on screen
nd. linel==83.				; line length used by ITS
nd. nlnglt==1				; number of lines to glitch when scrolling
nd. nsclin==5.				; number of seconds for clock interrupt
nd. nlnupd==4.				; number of lines that cause screen update
					; instead of updating individual lines

swdef. [debugp==0]Set ≠ 0 if to beep on a warning, <0 if to halt as well

nchars==<<<linel+5>/5>*5>		; number of characters per line, must
					; be a multiple of 5 for display stuff
					; to win


if2,[					; SWPRINT not defined until after next page
 swprint \pdllen,words of PDL storage.
 swprint \icpskt,is the ICP socket.

 radix 10.				; print these in decimal

 swprint \nlines,lines on the screen.
 swprint \linel,characters per line.
 swprint \nlnglt,lines per glitch when scrolling.
 swprint \nlnupd,minimum lines changed to cause full screen update.
 swprint \nsclin,seconds between clock interrupts.

 radix 8.				; back to octal
]
subttl AC's, I/O channels, macros

; Accumulators

;  I is an interrupt level AC and may not be used anywhere else.  Things
; depend on the order of X, Y, Z, and A being consecutive.  U is used at
; UUO level.  U, V, and W are also used in IMP status interrupts and must
; be consecutive.
 
acdef. [x y z a b c i u v w]

; I/O channels

;  ICP is used for ICP'ing only, NET is the general network work channel,
; DSK is only used for reading ROOMS[P,DOC].

acdef. [icp net dsk]
.hkill icp net dsk			; so DDT doesn't confuse these
					; with AC's on typeout

; Macros

; Print out switch settings

define swprint value,line/
 printx/value line
/
termin

; Map character in ac to char2 if it contains char1 now

define mapit ac,char1,char2
 caxn ac,char1
  jrst [movx ac,char2
	return]
termin

; Generate a Data Disc command

define ddcmd o1,d1,o2,d2,o3,d3
 .byte 8.,8.,8.,3.,3.,3.,3.
  d1 ? d2 ? d3 ? o1 ? o2 ? o3 ? 4
 .byte
termin
subttl SUPDUP documentation

COMMENT ⊗
		SUPer-DUPer Display TELNET to ITS
			  Mark Crispin

 INTRODUCTION:

SUPDUP is the SAIL implementation of the ITS SUPDUP program, which
is used for TELNETing between ITS sites.  This program uses the
internal ITS display codes for highly efficient communication and
full use of ITS display programs over the ARPAnet.  It runs on Data
Discs only.

When SUPDUP is run, it will prompt for the host name.  Type one or
two characters to identify the name of the ITS system you wish to
TELNET to (ie, either "A", "D", "MC", and "ML").  SUPDUP will then
establish a connection with the specified ITS site, and after that
you will effectively be a display on ITS, with full bucky bit
capability.

Some mappings in input and output are made due to the differences
between the SAIL and ITS ASCII character sets.  Most of these mappings
are transparent to the user.  The design philsophy behind the mappings
was to cause characters typed on the Stanford keyboard to be seen by
ITS as the character appears on the key tops, and for characters
received from ITS to be displayed as they would be at a console at MIT.

 NOTE!!!:

One thing that I should mention: you MUST NOT do a :TCTYP on ITS that
will set your terminal type.  SUPDUP's operation depends upon the
terminal type being SOFTWARE and things will not work correctly if
it is set to anything else.  It is alright to set certain other TCTYP
options such as SAIL character set enable, however, in general you
probably will not want to do any TCTYP at all.  SUPDUP sets the line
length and page size to the maximum possible on the screen.
 SUPDUP FEATURES:

  Visible OUTPUT MAPPINGS:

Caret is mapped to AND sign (∧) since there is no code in the SAIL
character set for caret.  There is no way to tell between AND sign and
caret.

  Visible INPUT MAPPINGS:

αz and αZ are mapped to [CALL], αβz and αβZ are mapped to α[CALL];
α_ is mapped to [BACK NEXT] and αβ_ is mapped to β[BACK NEXT]. ↑ is
mapped to caret.  VT will send the uparrow character, but without the
[TOP] bit; there is no way to send the [TOP]ified ↑ other then by using
[BACK NEXT]4013. Also, there is no way to send β[CALL] or αβ[CALL] other
than by using [BACK NEXT]432 and [BACK NEXT]632.

  COMMANDS:

[ESCAPE]I is used to enter a SUPDUP command.  The following commands
are defined:

	F	Use Fast display mode (discussed below)
	H	Type a help text
	K	Kill the job on ITS and break network connections
	L	Same as K command
	P	Temporarily restore the page printer.  Typing any
		character will return your screen to ITS.
	Q	Quit out, close network connections, detach the job
		on ITS if there is one.
	S	Use Slow display mode (see below)
	?	Same as H

In addition, in [ESCAPE]I mode, αz, αβz, αZ, αβZ, α_, and αβ_ are
sent as themselves without being mapped.  Maybe someday if β[CALL]
and αβ[CALL] become readable by a program then the mappings on z's will
be removed.

DISPLAY MODES:

SUPDUP has two display modes; fast and slow, which are set by the F and S
commands.  Fast mode, which is the default, is highly optimal on network
input and very fast on display.  On the other hand, it can be disconcerting
to have the screen flash as suddenly as it does with no semblance of line-
per-line output (it sort of comes out as chunk-per-chunk), therefore, there
is a slow mode which causes SUPDUP to output in the old-fashioned manner
which just does normal optimization but not line/screen optimization.

⊗
subttl Mappings between ITS and SAIL ASCII

;	Everything nobody wanted to know about SUPDUP's internal mappings...

;  The following character set mappings are in effect.  These mappings occur
; on both input and output, so in general they are invisible to the user.  In
; particular, the graphic on the keytop is what ITS will see, and what is
; displayed on the screen is what would be displayed on an ITS TV.  But see
; the second table and notes for exceptions.

;	SAIL		ITS
;	----		---
;
; 011	TAB		INT	(1)
;
; 013	 VT		 ↑
;
; 030	 _		 ←
;
; 032	 ~		 ≠
;
; 033	 ≠		ALT
;
; 136	 ↑		 ∧	(2)
;
; 137	 ←		 _
;
; 175	ALT		 }
;
; 176	 }		 ~


;  In addition, the following keyboard mappings are done:

;	KBD code	Sent to ITS
;	--- ----	---- -- ---
;
;	   αz		   [CALL]	(3)
;
;	   αZ		   [CALL]
;
;	  αβz		  α[CALL]
;
;	  αβZ		  α[CALL]
;
;	   α_		 [BACK NEXT]	(4)
;
;	  αβ_		α[BACK NEXT]
;
;	    ↑		     ∧		(2) (5)


; Notes:
;
; (1)	This character is image tab, which on a PDP-11 TV is output as
;	integral sign.
;
; (2)	AND sign (∧) is used for caret since there is no code in the SAIL
;	character set for caret anyway.
;
; (3)	These four mappings are necessary since there is no way that any
;	form of [CALL] can be read by a user program.  Perhaps if metized
;	[CALL]'s are allowed things will change.
;
; (4)	This mapping is necessary since there is no key remotely equivalent
;	to the [BACK NEXT] key.
;
; (5)	This mapping is necessary since otherwise there is no way to enter
;	caret from the keyboard.  As caret is more important on ITS, up
;	arrow lost.  VT will input an up-arrow, however it will not be
;	[TOP]ified, meaning that in order to enter this character into TECO
;	one must use a quoting convention.
subttl Data area

; Beginning of core area initialized to zero at startup

tmploc 41,jsr uuoser			; UUO server

	corbeg==.			; relocatable zero

cnsblk:					; CNSGET info
tctyp:	block 1				; TCTYP for server
ttyopt:	block 1				; TTYOPT for server
tcmxv:	block 1				; TTY page length
tcmxh:	block 1				; TTY width
cnsrol:	block 1				; CNSROL variable
cnsbll==.-cnsblk

; Random flags

filinp:	block 1				; -1 → fill in host name
runcmp:	block 1				; -1 → called via RUN command
slowip:	block 1				; -1 → do input slow way

; Interrupt pending flags

ttiinp:	block 1				; -1 → TTI pending
ntoinp:	block 1				; <0 → INS pending
ntiinp:	block 1				; -1 → NTI pending
escpip:	block 1				; -1 → <ESCAPE>I typed
imgchp:	block 1				; -1 → image αz, αβz, αZ, αβZ, α_, αβ_

; Buffer headers

ntibf:	block 3				; net input buffer header
ntobf:	block 3				; net output buffer header
dsibf:	block 3				; disk input buffer header

; Other random storage

lgrskt:	block 1				; socket from logger
pdl:	block pdllen			; pushdown stack

; These two locations must be in this order!!

mskbts:	block 1				; interrupt bits to go on
retnpc:	block 1				; PC to return to

; IMP MTAPE command words

; Connect to host command block

impcod:	block 1				; command
impsta:	block 1				; status
implsk:	block 1				; local socket
impwat:	block 1				; ≠ 0 → wait for connection
impbyt:	block 1				; byte size
impfsk:	block 1				; foreign socket
imphst:	block 1				; foreign host number

; Wait for connection to be completed command block

watcod:	block 1				; command
watsta:	block 1				; status
watskt:	block 1				; socket

; Close connection to host command block

clscod:	block 1				; close code
clssta:	block 1				; close status
clsskt:	block 1				; close socket
clswat:	block 1				; ≠ 0 → wait for close
subttl Display crufties

; Number of words in display frobs

nwrdln==2+nchars/5+1+1			; number of words on a line
ngw==<<nchars*3>+17.>/16.		; number of graphics words
scrsiz==nlines*<nchars/5+4>		; number of words on screen

; Cursor position pointers

vpos:	block 1				; vertical position
hpos:	block 1				; horizontal position
ovpos:	block 1				; old vertical position

; Positioning flags

govpos:	block 1				; -1 → get old vertical position
gohpos:	block 1				; -1 → get old horizontal position
gtvpos:	block 1				; -1 → get vertical position
gthpos:	block 1				; -1 → get horizontal position

; Insert/delete mode flags

gtiln:	block 1				; -1 → get # of lines to insert
gtdln:	block 1				; -1 → get # of lines to delete
gtich:	block 1				; -1 → get # of characters to insert
gtdch:	block 1				; -1 → get # of characters to delete

; Screen updating flags

slupdp:	block nlines			; -1 → this line has changed
scupdp:	block 1				; -1 → some update happened someplace
saupdp:	block 1				; -1 → updated whole screen
crupdp:	block 1				; -1 → updated cursor

corend==.-1				; address of top of core

; End of core zeroed upon startup

; Various display programs

; Erase screen display program

sce:	ddcmd 1,17,1,17,2,0		; erase screen
	0				; all done
scel==.-sce

; Display screen display program

scp:	ddcmd 1,46,4,1,5,10		; line address 30
	ddcmd 3,2,3,2,3,2		; go to column 2
screen:	block scrsiz			; TV screen storage
scrend=.-1				; end of screen storage
	0				; end of DD program
scpl==.-scp
botlin=screen+scrsiz-nwrdln+2-1		; address of start of bottom line

; Display cursor display program

scc:	ddcmd 1,7,1,7,1,7		; graphics
	ddcmd 3,1,4,0,5,0		; select position
	block ngw			; all graphics columns
	ddcmd 0,0,1,46,1,46		; execute
	0				; end of program
sccl==.-scc
; More display data stuff

; Display commands

; Clear screen

sclear:	sce				; address of display program
	scel				; size of display program
	0 ? 0				; no t-in-p flag, line command addr

; Display screen

sdisp:	200000,,scp			; two field mode
	scpl				; size of display program
	0				; no transfer in progress flag
	scp				; address of low order line command

; Cursor display

cdisp:	scc				; address of cursor hacker
	sccl				; size of the hacker
	0				; no transfer in progress flag
	scc+1				; address of low order line command

; Line display

ldisp:	200000,,0			; two field mode
	nwrdln				; size of this command
	0 ? 0				; no t-i-p flag, l.c.a. gets hacked

; Byte pointer table for insertions

scbytp:	350700,,(y)
	260700,,(y)
	170700,,(y)
	100700,,(y)
	010700,,(y)
subttl ITS TTY definitions

;  These definitions are the various bits, words, etc. from the
; ITS TTY system calls and are here for convenience and clarity

; TTYOPT variable (terminal capabilities)

%toalt==200000,,			; 1 → standardise altmodes
%toclc==100000,,			; 1 → convert cases on input
%toers==040000,,			; 1 → this terminal can erase
%tohdx==020000,,			; 1 → half duplex
%tomvb==010000,,			; 1 → can backspace
%tosai==004000,,			; 1 → has SAIL graphics
%tosa1==002000,,			; 1 → use SAIL graphics
%toovr==001000,,			; 1 → can overprint
%tomvu==000400,,			; 1 → can line starve (ie a display)
%tomor==000200,,			; 1 → do **More** processing
%torol==000100,,			; 1 → scroll instead of wraparound
%toraw==000040,,			; 1 → no cursor motion optimization
%tolwr==000020,,			; 1 → lower case keyboard
%tofci==000010,,			; 1 → has bucky bit keyboard
%toiml==000004,,			; 1 → acts like a grIMLAC
%tolid==000002,,			; 1 → can insert/delete lines
%tocid==000001,,			; 1 → can insert/delete characters
%tpplf==700000				; LF padding
%tppcr==070000				; CR padding
%tpptb==007000				; TAB padding (0 → no tabs, 1 → tabs)
%tptel==000100				; 1 → CR → CRLF for ARPAnet protocol
%tpcbs==000040				; 1 → intelligent terminal protocol
%tp11t==000020				; 1 → PDP-11 TV
%tpors==000010				; 1 → output reset should do something
%tpibc==000002				; 1 → correspondence code 2741
%tpibm==000001				; 1 → IBM 2741

; TTYOPT bits for a Data Disc

ddbits==%toers\%tomvb\%tosai\%tosa1\%tomvu\%tomor\%tolwr\%tofci\%tolid\%tocid
ddbits==ddbits\%tpcbs\%tpors

; TCTYP variable (terminal type)

%tnprt==0				; printing console, glass TTY, etc.
%tndp==1				; good Datapoint
%tnodp==2				; inferior losing Datapoint
%tniml==3				; grIMLAC
%tntek==4				; Tektronix 4000 series
%tntv==5				; PDP-11 TV
%tnmem==6				; Memowreck
%tnsfw==7				; Software
%tntrm==10				; Terminet
%tnesc==11				; ASCII standard display (VT52, etc.)
%tndtm==12				; Datamedia 2500

; Bucky bits

%txctl==0200				; control
%txmta==0400				; meta
%txsft==1000				; shift
%txsfl==2000				; shift lock
%txtop==4000				; top
subttl ITS output buffer codes

; These are the ITS output buffer codes (used by Software terminals).

%tdmov==200				; move cursor OV OH NV NH
%tdmv1==201				; impossible; NV NH
%tdeof==202				; clear to end of screen
%tdeol==203				; clear to end of line
%tddlf==204				; delete character after cursor
%tdmtf==205				; motor off
%tdmtn==206				; motor on
%tdcrl==207				; terpri
%tdnop==210				; no-op
%tdbs==211				; backspace
%tdlf==212				; line feed
%tdrcr==213				; carriage return
%tdors==214				; output reset
%tdqot==215				; ???
%tdfs==216				; cursor forward
%tdmv0==217				; move cursor NV NH
%tdclr==220				; clear screen
%tdbel==221				; feep!
%tdini==222				; reset reset reset
%tdilp==223				; insert line
%tddlp==224				; delete line
%tdicp==225				; insert character
%tddcp==226				; delete character
%tdbow==227				; inverse video
%tdrst==230				; reset inverse video, etc.
subttl Interrupt and UUO service

;  UUO server.  Only allows BURP UUO (op code 037).  If DEBUGP≠0, beep as well,
; and if DEBUGP<0, halt too.

BURP=037000,,				; UUO for logging cruft

uuoser:	0				; called via JSR, last impure location(!!)
	ldb u,[331100,,40]		; get op code
	caxe u,burp←-27.		; was it a BURP UUO?
	 jrst [	outstr [asciz/Illegal UUO!/]
		jrst 4,.-1]		; glork!
	outstr @40			; type the message
ifn debugp,[
	movx u,%fword			; this console
	beep u,				; feep!
ifl debugp,jrst 4,.+1			; if super paranoia mode set
]
	jrst 2,@uuoser			; return to user

; Interrupt server

; Interrupt condition bits

inttty==020000,,			; TTY input activation
intclk==000200,,			; clock interrupt
intins==000040,,			; IMP INS
intims==000020,,			; IMP status change
intinp==000010,,			; IMP input waiting
inttti==000004,,			; <ESCAPE>I

;  Nothing is done at interrupt level other than to determine the
; cause of the interrupt and set bits for the main program level
; to use.  This is because SAIL interrupt service is nothing like
; ITS interupt service and you can only be at interrupt for 8
; jiffies and system calls will foul up in general and so on,
; unlike ITS user TELNET which can spend large amounts of time at
; interrupt level without harm.

intser:	skipn i,jobcni			; get reason for interrupt
	 jrst 4,.-1			; spurious interrupt?
	txze i,inttty			; got a character?
	 store %fword,ttiinp		; yup, TTI on on on
	txz i,intclk			; just ignore clock interrupts
	txze i,intins			; IMP INS?
	 sos ntoinp			; yes, flag net output interrupt
	txze i,intinp			; IMP input?
	 store %fword,ntiinp		; yup, flag IMP input
	txze i,inttti			; <ESCAPE>I?
	 store %fword,escpip		; yup, command time
	txze i,intims			; IMP status change?
	 jrst netser			; yes, hack net status change
luzint:	jumpn i,[	outstr [asciz/Spurious interrupt!
/]
			jrst 4,.]	; funny interrupt bit?
	dismis				; yes, dismiss interrupt

; Network status interrupt.  Find out what happened and maybe die.

netser:	xct luzint			; check for garbage
	move u,jobtpc			; get PC at the interrupt
	movem u,retnpc			; save it as return PC
	store %fword,mskbts		; all masking bits
	imskcl mskbts			; go off
	uwait				; finish up any UUO in progress
	debreak				; leave interrupt level
	movx u,2			; get status
	mtape net,u			; get network status
	ior v,w				; merge status bits together
	txne v,(60000)			; connection closed?
	 jrst diedie			; lose lose
	intdej mskbts			; sigh, well, hurry on back
subttl Startup, etc.

;  Initialize the world; clear all I/O and other things; give
; back any unneeded core to the monitor; clear data area, and
; set up the stack pointer.

supdup:	jfcl				; flush CCL crufties
	reset				; reset all I/O
ifn debugp,[
	outstr [asciz/
Warning!!  This is a debugging version/]
ifl debugp,outstr [asciz/ with breakpoints and may stop at any time/]
	outstr [asciz/!!
/]
]
	movei intser			; get addr of interrupt server
	movem jobapr			; tell monitor
	hlrz jobsa			; get size I should be
	movem jobff			; make sure monitor knows
	core				; in case I grew
	 jfcl				; you ingrate!
	store %zeros,corbeg,corend	; zak!
	move p,[pdl(-pdllen)]		; load PDP

;  Check terminal characteristics; this program will only work
; on a Data Disc.

	movx x,%fword			; my console
	getlin x			; get my line characteristics
	caxn x,%fword			; detached?
	 exit				; yes, die die die
	txnn x,(20000)			; is this a Data Disc?
	 jrst [	outstr [asciz/SUPDUP only runs on Data Discs./]
		exit]			; maybe III someday

; Set terminal modes; no echo and activate on all characters

	ptjobx [0 ? sixbit/DOFF/]	; turn echoing off
	txo x,(100)			; special activation mode bit
	setlin x			; enter SAM
	setact [[777777,,777777		; activate on 000 - 043
		 777777,,777777		;  044 - 107
		 777777,,777777		;  110 - 153
		 777777,,600066]]	;  154 - 177, αβ activate, etc

; Set up terminal codes for ITS and the sort of display we are

	store %tnsfw,tctyp		; software TTY
	store ddbits,ttyopt		; what we can support
	store nlines,tcmxv		; vertical screen size
	store linel,tcmxh		; horizontal screen size
	store nlnglt,cnsrol		; number of lines to glitch
subttl Monitor command processor

;  Check for host name in the monitor command line.  Yes, I realize this
; code is totally wierd!!!

	rescan x			; get monitor command cruft back
	jumpe x,gethst			; no cruft, ask for it
moncom:	inchrs x			; got a command, gobble a character
	 jrst gethst			; lost, do it manually
	caxl x,"a			; lower case?
	 txz x,<" >			; yes, uppercaseify
	skipn runcmp			; already checked for RUN command?
	 jrst [	caxe x,"R		; is it a RUN command?
		 aosa runcmp		; nope
		  store %fword,runcmp	; yes, no spaces checked!
		jrst .+1]		; now return
	skipl runcmp			; called via RUN command?
	 caxe x,<" >			; space frob? (only if not RUN)
	  caxn x,<";>			; or comment?
	   caxa				; yup, hack it
	    jrst moncom			; haven't gotten there yet, try again
	move b,[jsp y,[	inchrs x	; yes, load subroutine
			 jrst badhst	; lost
			caxl x,"a	; lower case?
			 txz x,<" >	; yes, uppercaseify
			caxn x,<" >	; found space?
			 jrst -1(y)	; yes, flush it
			jrst (y)]]	; end of subroutine
	jrst scnhst			; and scan for this host
subttl Get host name

gethst:	outstr [asciz/Host = /]
	move b,[jsp y,[	inchrw x	; subroutine for non-monitor command
			caxl x,"a	; lower case?
			 txz x,<" >	; yes, uppercaseify
			outchr x	; echo the whatever
			jrst (y)]]	; end of non-monitor subroutine
	store %fword,filinp		; remember to fill in host name
scnhst:	xct b				; get a character
	caxn x,"A			; AI Lab?
	 jrst [	skipe filinp		; fill in host name?
		 outchr ["I]		; yes
		movx a,sixbit/AI/	; select host name
		setnam a,		; and tell monitor
		movx a,206		; MIT-AI
		jrst goicp]		; now ICP
	caxn x,"D			; Dynamod?
	 jrst [	skipe filinp		; fill in host name?
		 outchr ["M]		; yes
		movx a,sixbit/DM/	; select host name
		setnam a,		; and tell monitor
		movx a,106		; MIT-DMS
		jrst goicp]		; now ICP
	caxe x,"M			; MathLab LCS place?
badhst:	 jrst [	outstr [asciz/?
/]
		clrbfi			; flush input buffer
		jrst gethst]
	xct b				; get another character
	caxl x,"a			; lower case?
	 trz x,<" >			; uppercaseify
	caxn x,"C			; MACSYMA consortium?
	 jrst [	movx a,sixbit/MC/	; select host name
		setnam a,		; and tell monitor
		movx a,354		; MIT-MC
		jrst goicp]		; now ICP
	caxe x,"L			; Autoprog?
	 jrst badhst			; nope, losey
	movx a,sixbit/ML/		; select host name
	setnam a,			; tell monitor
	movx a,306			; MIT-ML
;	jrst goicp			; now ICP
subttl ICP ICP ICP

goicp:	clrbfi				; clear any crlf, etc.
	outstr [asciz/
 Trying... /]

; Open channels and set timeouts

	init icp,17			; open ICP in dump mode
		'IMP,,			; ARPAnet
		0			; no buffers
	 jrst icpluz			; oh well
	mtape icp,[	17		; set timeouts
			.byte 6 ? 2 ? 24 ? 0 ? 7 ? 7 ? 0]
	init net,0			; open NET in ASCII mode
		'IMP,,			; ARPAnet
		ntobf,,ntibf		; buffers
	 jrst icpluz			; rather screwy
	mtape net,[	17		; set timeouts
			.byte 6 ? 2 ? 24 ? 0 ? 7 ? 0 ? 0]

;  Try to generate a unique socket number, using job number and
; time of day to avoid lossage due to old connections.
; Algorithm used is: job #,,<time&777770>

	pjob x,				; get my job #
	mstime y,			; and the time now
	lsh x,18.			; put job # in LH
	hrri x,(y)			; and time in RH
	andx x,37777777770		; but zap low order bits

; Now try to get to the foreign place's server

insirp setzm,[impcod impsta impbyt]
	store %fword,impwat		; do wait until timeout
	movem x,implsk			; my socket to use
	movem x,clsskt			; socket to close when done
	movem a,imphst			; host to go to
	store icpskt,impfsk		; socket to ICP on
	mtape icp,impcod		; connect → foreign logger
	move x,impsta			; get status
	txnn x,77			; error code?
	 statz icp,763600		; or error bits?
	  jrst icpluz			; so sorry
	txc x,(300000)			; for next instruction to win
	txne x,(300000)			; RFC sent+received?
	 jrst icpluz			; nope, lose
	move y,[iowd 1,impfsk]		; get ready to get a word
	movx z,%zeros			; stop after

; (continued on next page)
; (continued from previous page)

; Get socket number from logger

	in icp,y			; get socket from logger
	 caxa				; won
	  jrst [outstr [asciz/Did not get socket number from foreign host!/]
		jrst 4,.-2]
	move x,impfsk			; load socket we got
	lsh x,-4			; compensate for left justification
	movem x,impfsk			; and save it back
	store 3,clscod			; close code
	mtape icp,clscod		; close off ICP socket
	releas icp,			; free up channel

; Got socket number from logger; now connect output

	movx x,3			; ICP/transmit offset
	addb x,implsk			; local transmit socket
	movem x,watskt			; save wait socket
	store %zeros,impwat		; don't wait
	store 8.,impbyt			; byte size
	mtape net,impcod		; connect → server output
	move x,impsta			; get status
	txne x,77			; error code?
	 jrst icpluz			; lose lose lose

; Now connect input

	sos implsk			; local receive socket
	aos impfsk			; foreign transmit socket
	mtape net,impcod		; connect ← server input
   	move x,impsta			; get status
	txne x,77			; error code?
	 jrst icpluz			; lose lose lose

; Now wait until we get the connection

	store 4,watcod			; WAIT code
	mtape net,watcod		; wait for output
	move x,watsta			; get status
	txne x,77			; error?
	 jrst icpluz			; lose lose lose
	sos watskt			; now select receive socket
	mtape net,watcod		; wait for input
	move x,watsta			; get status
	txne x,77			; error?
	 jrst icpluz			; lose lose lose
	statz net,763600		; error bits?
	 jrst icpluz			; too bad

	outstr [asciz/Open
/]
subttl Final pre-display initialization

; Random other pre-execution initialization crufties

	movx x,8.			; 8 bit bytes you know
	dpb x,[300600,,ntibf+1]		; hack input buffer
        dpb x,[300600,,ntobf+1]		; and output buffer
	movx x,inttty\intclk\intins\intims\intinp\inttti
	intenb x,			; enable interrupt conditions
	clkint nsclin*60.		; get a clock interrupt every n secs
	mtape net,[15 ? 1]		; maximum allocation
	outbuf net,4			; allow for fast typists

; Send terminal characteristics

	move z,[440600,,cnsblk]		; load sixbit pointer to TTY chars
	movx y,6*cnsbll			; load number of bytes to do
ttchsn:	ildb x,z			; get a character
	call netoc1			; output it
	sojg y,ttchsn			; loop until done
	call netsnd			; now force it out

; Now get server's greeting message

grtmsg:	call netich			; get a character from the network
	caxn x,%tdnop			; hit the no-op yet?
	 jrst grtdun			; yes, greeting message done
	outchr x			; output it
	jrst grtmsg			; and loop for next

; Make sure we can slurp up what is there now due to our hacking

grtdun:	store %fword,ntiinp		; will try to slurp slurp slurp now
subttl Slurp up and send terminal ID

; Tell SUPSER to expect terminal name

	movx x,300			; escape to SUPSER
	call netoc1			; send it
	movx x,302			; set TTY id
	call netoc1			; send it

; Now try to get it

	open dsk,[0 ? 'DSK,, ? dsibf]	; try to get a DDB
	 jrst rndtid			; really losing
	movx x,sixbit/ROOMS/		; file name
	setzb y,z			; extension, date cruft
	movx a,sixbit/  PDOC/		; PPN
	lookup dsk,x			; try to find file
	 jrst rndtid			; lost

; Compute name we must look for

	movx y,('TTY)			; console TTY name
	devnum y,			; get our TTY #
	 jrst rndtid			; losey
	idivx y,100			; siphon off high order digit
	idivx z,10			; and two low order digits

; Now search for TV-...

search:	irpc ch,,[TV-]
	 jsr getch			; get a character
	  jrst search			; CR can't win
	 caxe x,"ch			; got it?
	  jrst search			; not yet
	termin
; Now check to see if we have a reasonable match

	jsr getch			; get a character for the number
	 jrst search			; somebody better fix ROOMS[P,DOC] !!
	jumpe y,serch1			; low order terminal
	cain x,"0(y)			; win so far?
	 jsr getch			; get next character
	  jrst search			; nope, we're still losing
serch1:	cain x,"0(z)			; won?
	 jsr getch			; almost there
	  jrst search			; nope
	caie x,"0(a)			; got a match now?
	 jrst search			; nope, sorry

; Found the terminal name, now send it along

fndrom:	jsr getch			; gobble down spaces
	 jrst sntrom			; all done I guess
	caxn x,<" >			; leading space?
	 jrst fndrom			; yes, flush it
sndrom:	call netoc1			; send character out
	jsr getch			; get a character
	 jrst sntrom			; all done I guess
	caxe x,<" >			; saw a space?
	 jrst sndrom			; nope, okay to send it
	call netoc1			; well, can send one space
flsspc:	jsr getch			; but not any more
	 jrst sntrom			; all done
	caxn x,<" >			; a space to flush?
	 jrst flsspc			; yes, flush it
sndtid:	call netoc1			; not a space, send it
	jsr getch			; get a character
	 caxa				; all done
	  jrst sndtid			; no, send it out

; Done with sending room, finish that up and get going on real work

sntrom:	movx x,%zeros			; final null
	call netoc1			; send it
tidone:	call netsnd			; force the buffer out
	release dsk,			; free up channel

; Initialize screen

	ppact 0				; flush PP 0
	leypos 2000			; line editor off screen
	ddupg sclear			; zap screen
	hrroi x,[004000,,"W]		; restore wholine quickly
	ttyset x,			; by doing <ESCAPE>W
	call scrini			; init core screen
	store %fword,ovpos		; old vertical position
	ddupg sdisp			; display the screen
	call csrupd			; give a cursor
	lock				; now get locked in core
	jrst mainlp			; and enter main loop
subttl Main program loop, clock interrupt

; Main program loop

zzzzzz:	call scnupd			; update screen if necessary
	iwait				; bye bye

; Something woke us up.  Find out what

mainlp:	call scnupd			; update screen if necessary
	aosg escpip			; <ESCAPE>I typed?
	 jrst cmdcmd			; yes, process command
	aosg ttiinp			; TTY input available?
	 jrst ttiser			; yes, slurp slurp
	aosg ntiinp			; network input available?
	 jrst ntiser			; yes, get network input

;  On a clock interrupt we just check the input frobbies to
; make sure we didn't lose an int somehow

	inskip				; got a character?
	 caxa				; nope
	  jrst ttisr1			; yes, do it do it do it
	mtape net,[10]			; network input?
	 jrst zzzzzz			; nope
	setzm ntiinp			; yes, clear flag if was on
	jrst ntiser			; now hack net input
subttl TTY input service

ttiser:	inskip				; got a character?
	 jrst mainlp			; nope, back to main loop
ttisr1:	inchrw x			; get a character
	ldb y,[000700,,x]		; get ASCII part of X
	caxn y,↑M			; terpri?
	 inchrw y			; gobble line feed
	call netoch			; send it out
	inskip				; any more?
	 caxa				; no, force buffer out
	  jrst ttisr1			; else hack the extra characters
	call netsnd			; send the buffer out
	jrst ttiser			; and try for any frobs just came in

; Force the buffer out to the network

netsnd:	ldb x,[410300,,ntobf+1]		; load position field
	movx y,1			; get a bit to hack
	lsh y,(x)			; 2↑# of characters
	subx y,1			; now get null bit flusher mask
	iorm y,@ntobf+1			; make sure the nulls aren't sent
	out net,			; send the character
	 return				; won
	jrst diedie			; lost

; Auxillary NETOCH

netoc1:	sosg ntobf+2			; space available in buffer?
	 out net,			; no, output the buffer
	  caxa				; win
	   jrst diedie			; lose
	idpb x,ntobf+1			; put character in buffer
	return				; and return
; Output a character to the network buffer in the hairy way

netoch:	sosg ntobf+2			; space available in buffer?
	 out net,			; no, output the buffer
	  caxa				; win
	   jrst diedie			; lost
	aosn imgchp			; image characters?
	 jrst netoc2			; yes, don't map then

;  Map αZ to [CALL], αβZ to α[CALL], α_ to [BACK NEXT], αβ_ to α[BACK NEXT].
; αz and αβz will behave in a similar manner.
;  These mappings are necessary since there is no way that SUPDUP can read a
; [CALL] coming in for the Stanford keyboard.  This may someday be changed if
; the system is changed so that a program can see β[CALL] and αβ[CALL].  In
; any case there is no way that either β[CALL] or αβ[CALL] can be sent to ITS
; other than by [BACK NEXT]432 and [BACK NEXT]632 - sorry!

	ldb y,[001000,,x]		; get character with [CONTROL]
	caxe y,%txctl\"z		; some form of αz?
	 caxn y,%txctl\"Z		; or of αZ?
	  jrst [movx y,↑Z		; yes, convert to [CALL]
		dpb y,[001000,,x]	; save character
		txze x,%txmta		; αβz or αβZ?
		 iorx x,%txctl		; yes, make it α[CALL]
		jrst netoc3]		; now send this bucky command
	caxn y,%txctl\"_		; α_?
	 jrst [	movx y,↑←		; yes, convert to [BACK NEXT]
		dpb y,[001000,,x]	; save character
		txze x,%txmta		; αβ_?
		 iorx x,%txctl		; yes, make it α[BACK NEXT]
		jrst netoc3]		; now go send the frob
;	jrst netoc2			; else fall through
; More output mapping stuff

;  Map the character from the SAIL to the ITS character set and check for
; if TOPififcation is needed (TECO will treat SAIL graphics as controls
; unless %TXTOP is on).  Then check for any bucky bits, and if any, then
; do it the hairy way.

netoc2:	ldb y,[000700,,x]		; get ASCII part of character
	call outmap			; map to ITS ASCII
	dpb y,[000700,,x]		; and kludge back
	caxl y,↑J			; LF is not TOPified
	 caxle y,↑M			; neither are VT, FORM, and CR
	  caxn y,<↑[>			;]neither is ALT
	   jrst ntoc2a			; nope, it's a positioning(?) frob
	caxge y,<" >			; all SAIL graphics
	 iorx x,%txtop			; are TOPified (happy TECO)
ntoc2a:	txnn x,%txtop\%txsfl\%txsft\%txmta\%txctl; any bucky bits?
	 jrst [	idpb x,ntobf+1		; nope, just send the frob
		caxn x,"≤		; sending the escape code?
		 call netoc1		; yes, repeat it
		return]			; now return

;  The character has bucky bits, so the intelligent terminal protocol is used to
; send bucky bits: [↑\] [<bucky bits>←-7] [<character>].

netoc3:	movx y,↑\			; load escape code
	idpb y,ntobf+1			; put character in buffer
	movx y,"@			; initialize bucky word
	txze x,%txtop			; [TOP] set?
	 txo y,%txtop←-7		; yes, use it then
;
;  Nobody in their right mind would write a program on ITS that uses %txsfl and
; %txsft, so it's not worth the runtime to implement.
;
;	txze x,%txsfl			; [SHIFT LOCK]?
;	 txo y,%txsfl←-7		; uselessness
;	txze x,%txsft			; [SHIFT]?
;	 txo y,%txsft←-7		; more uselessness
	txze x,%txmta			; β character?
	 txo y,%txmta←-7		; yup
	txze x,%txctl			; α character?
	 txo y,%txctl←-7		; yup
	exch x,y			; swap swap swap
	call netoc1			; send this cruftie out
	exch x,y			; swap back
	call netoc1			; now send the non-bucky character
	return				; and return

;  Output mapping from SAIL to ITS character set.  The idea is that the Stanford
; keyboard appears as a strange type of Knight keyboard.

outmap:	mapit y,030,137			; underscore
	mapit y,032,176			; tilde
	mapit y,033,032			; not equals
	mapit y,137,030			; backarrow
	mapit y,175,033			; diamond
	mapit y,176,175			; right curly bracket
	return				; else return
subttl Network input service

ntiser:	skiple ntibf+2			; maybe there is some cruft
	 jrst ntisr1			;  from before...
ntisr2:	mtape net,[10]			; any input available?
	 jrst mainlp			; no, return
	in net,				; yes, get a new buffer
	 caxa				; won
	  jrst diedie			; lost
ntisr1:	sosge ntibf+2			; anything in buffer?
	 jrst ntisr2			; nope, try another
	call nulfls			; flush nulls
	ldb x,ntibf+1			; get a byte
	skipge ntoinp			; still hacking output reset?
	 caxn x,%tdors			; got an output reset?
	  caxn x,377			; padding null?
	   jrst ntisr1			; sigh

; Check for any display stuff that must be done

	aosn govpos			; get old vertical position?
	 jrst [	store %fword,gohpos	; yes, now get old horizontal position
		jrst ntisr1]		; and try for next
	aosn gohpos			; get old horizontal position?
	 jrst [	store %fword,gtvpos	; yes, get vertical position now
		jrst ntisr1]		; and try for next
	aosn gtvpos			; get vertical position?
	 jrst [	store %fword,gthpos	; yes, get horizontal position now
		movem x,vpos		; save current vpos now
		store %fword,crupdp	; flag cursor updated
		jrst ntisr1]		; and try for next
	aosn gthpos			; get horizontal position?
	 jrst [	movem x,hpos		; set horizontal position
		store %fword,crupdp	; flag cursor updated
		jrst ntisr1]		; and continue
	aosn gtiln			; insert lines?
	 jrst inslin			; yup
	aosn gtdln			; delete lines?
	 jrst dellin			; yup
	aosn gtich			; insert characters?
	 jrst inschr			; yup
	aosn gtdch			; delete characters?
	 jrst delchr			; yup
	caxle x,177			; display code?
	 jrst dpyser			; yes, go do special things

; Check for garbage received and flush it

	jumpe x,[	burp [asciz/Spurious input NUL flushed.
/]
			jrst ntisr1]	; I think NULs can't happen anymore
	caxn x,↑J			; image LF?
	 jrst [	burp [asciz/Spurious input image LF flushed.
/]
		jrst ntisr1]		; should not happen
	caxn x,↑M			; image CR?
	 jrst [	burp [asciz/Spurious input image CR flushed.
/]
		jrst ntisr1]		; should not happen
	caxn x,177			; rubout?
	 jrst [	burp [asciz/Spurious input RUBOUT flushed.
/]
		jrst ntisr1]		; this shouldn't happen I think

; Good character, so display it

	call inpmap			; map from ITS to SAIL ASCII
	call scstor			; store it on the screen
	jrst ntisr1			; continue until this frob empty
; Subroutines for network input service

; Read a character from the network, hanging for it

netich:	sosg ntibf+2			; anything in buffer?
	 in net,			; nope, get some
	  caxa				; won
	   jrst diedie			; lost
	call nulfls			; call null flusher crock
	ldb x,ntibf+1			; get a byte
	caxn x,377			; padding null?
	 jrst netich			; yup
	pjrst inpmap			; map from ITS to SAIL ASCII

;  Map graphics from ITS extended ASCII to SAIL's extended ASCII.
; First comes mappings which are done going anywhere.

inpmap:	mapit x,032,033			; not equals
	mapit x,033,175			; diamond
	mapit x,175,176			; right curly brace
	mapit x,176,032			; tilde

; These are mappings necessary between SAIL and ITS ASCII

	mapit x,011,013			; integral sign
	mapit x,013,136			; uparrow
	mapit x,030,137			; left arrow
	mapit x,136,004			; caret (sigh!!!)
	mapit x,137,030			; underscore
	return				; and return

;  Flush nulls and bump byte pointer.  Assumes that no data bytes follow
; padding bytes in a word.

nulfls:	ibp ntibf+1			; point to byte we're going to hack
	move x,@ntibf+1			; get word of that byte
	andx x,17			; only marking bits
	jffo x,.+2			; count leading zeros
	 return				; no nulls to flush
	andcam x,@ntibf+1		; turn off padding bits
	move y,-32.(y)+[.byte 8 ? 377 ? 377 ? 377 ? 377
			.byte 8 ? 000 ? 377 ? 377 ? 377
			.byte 8 ? 000 ? 000 ? 377 ? 377
			.byte 8 ? 000 ? 000 ? 000 ? 377]
	iorm y,@ntibf+1			; hack out trailing nulls
	return				; normal return
subttl Display hacking

dpyser:	caxle x,%tdrst			; a baddie?
	 jrst [	outstr [asciz/Spurious input %TD code (/]
		idivx x,100		; get hundreds
		idivx y,10		; and tens and ones
		repeat 3,[
		 addx x+.rpcnt,"0	; ASCIIify
		 outchr x+.rpcnt	; and print it
		]			; once for each digit
		burp [asciz/) flushed.
/]
		jrst ntisr1]		; yes, report it
	xct dpyctb-200(x)		; no, dispatch on it
	jrst ntisr1			; return

;  Dispatch table for ITS cursor control codes.  The server for
; a display code is defined by:
;	DPYSVR code,server instruction
; The servers must be in order by their codes!

define dpysvr code,server
 ifn .-dpyctb-code+200,.err code is out of order
 server
termin

dpyctb:	dpysvr %tdmov,[store %fword,govpos]
	dpysvr %tdmv1,[store %fword,gtvpos]
	dpysvr %tdeof,[call clreof]
	dpysvr %tdeol,[call clreol]
	dpysvr %tddlf,[call clr1ch]
	dpysvr %tdmtf,[burp [asciz/Spurious input %TDMTF flushed.
/]]
	dpysvr %tdmtn,[burp [asciz/Spurious input %TDMTN flushed.
/]]
	dpysvr %tdcrl,[call terpri]
	dpysvr %tdnop,[jfcl]
	dpysvr %tdbs,[burp [asciz/Spurious input %TDBS flushed.
/]]
	dpysvr %tdlf,[burp [asciz/Spurious input %TDLF flushed.
/]]
	dpysvr %tdrcr,[burp [asciz/Spurious input %TDRCR flushed.
/]]
	dpysvr %tdors,[call oreset]
	dpysvr %tdqot,[burp [asciz/Spurious input %TDQOT flushed.
/]]
	dpysvr %tdfs,[call csraos]
	dpysvr %tdmv0,[store %fword,gtvpos]
	dpysvr %tdclr,[call clrscn]
	dpysvr %tdbel,[call bredle]
	dpysvr %tdini,[burp [asciz/Spurious input %TDINI flushed.
/]]
	dpysvr %tdilp,[store %fword,gtiln]
	dpysvr %tddlp,[store %fword,gtdln]
	dpysvr %tdicp,[store %fword,gtich]
	dpysvr %tddcp,[store %fword,gtdch]
	dpysvr %tdbow,[burp [asciz/Spurious input %TDBOW flushed.
/]]
	dpysvr %tdrst,[burp [asciz/Spurious input %TDRST flushed.
/]]
subttl Display subroutines

;  Note: none of these routines attempt to perform any wraparound if the
; line gets too large; they trust ITS to do all the work.  This is okay
; since ITS SUPDUP will die too if the other ITS sends garbage.

; Here to initialize the screen image in core

scrini:	store ascii/     /+1,screen,scrend; write blanks throughout screen
	movx x,<ascii/
/+1>					; DD type of terpri
	movx y,%zeros			; top line
	movx z,1			; blank word
	movx a,nlines			; do for number of lines on screen
scrin1:	movem z,screen(y)		; zap first word on line
	movem z,screen+1(y)		; and second one too
	movem x,screen+nwrdln-2(y)	; put terpri at end
	movem z,screen+nwrdln-1(y)	; and nothingness after that
	addx y,nwrdln			; go to next line
	store %zeros,slupdp-1(a)	; line not updated
	sojg a,scrin1			; loop for next line
glnini:	store 2,scc+2,scc+2+ngw-1	; blank graphics word
	return				; now return

; Here to store a character on the screen

scstor:	move y,vpos			; line position
	caxl y,nlines			; gone too far?
	 jrst [	move y,[screen+nwrdln,,screen]; foo!  gotta scroll (sigh)
		blt y,screen+scrsiz-nwrdln-1; the big BLT strikes again
		store ascii/     /+1,botlin+1,botlin+<nchars/5>
		store %fword,saupdp	; I can't believe I updated the WHOLE thing
		store nlines-1,vpos,,y	; set vertical position to bottom line
		jrst .+1]		; and continue
	store %fword,slupdp(y)		; flag this line changed
	store %fword,scupdp		; and that there is a change
	imulx y,nwrdln			; number words/line
	move z,hpos			; x position
	caxle z,linel			; greater than line length
	 jrst [	burp [asciz/Attempt to output a character beyond end of line.
/]
		aos hpos		; account for it anyway
		return]			; and flush the attempt
	idivx z,5			; word position
	addi y,screen+2(z)		; address of word to hack
	dpb x,scbytp(z+1)		; save character on screen
	aos hpos			; bump X position
	return				; and return

; Here to clear the screen

clrscn:	store %zeros,vpos		; top line
	store %zeros,hpos		; leftmost column
	call scrini			; initialize screen
	store %fword,saupdp		; updated entire screen
	call scnupd			; now update the screen
	return				; and return
; Non-insert/delete display subroutines

; Here to clear to EOL

clreol:	save hpos			; save horizontal position
cleol1:	movx x,<" >			; space in the character
	call scstor			; now put it on the screen
	move x,hpos			; get the position now
	caxg x,linel			; got to EOL yet?
	 jrst cleol1			; nope, not done yet
	retr hpos			; yup, all done
	return				; and return

; Here to delete a character forward

clr1ch:	movx x,<" >			; a blank space
	move y,vpos			; line position
	store %fword,slupdp(y)		; flag this line changed
	store %fword,scupdp		; and that a change happened
	imulx y,nwrdln			; number of words/line
	move z,hpos			; horizonal position
	idivx z,5			; word position
	addi y,screen+2(z)		; address to be hacked
	dpb x,scbytp(z+1)		; shove character in
	return				; and return

; Here to terpri

terpri:	store %zeros,hpos		; to beginning of line
	aos vpos			; bump vertical position
	store %fword,crupdp		; flag cursor has moved
	pjrst clreol			; and now clear the line

; Here to breedle

bredle:	movx x,%fword			; → own speaker
	beep x,				; breedle...
	return				; and return

; Here to respond to an output reset

oreset:	movx x,↑\			; escape code
	call netoc1			; send it
	movx x,↑P			; ready to send cursor position
	call netoc1			; here it comes...
	move x,vpos			; vertical position
	call netoc1			; . . .
	move x,hpos			; horizontal position
	call netoc1			; . . .
	aos ntoinp			; flush one net interrupt
	pjrst netsnd			; force these crufies out

; Here to forespace

csraos:	aos hpos			; bump horizontal position
	store %fword,crupdp		; flag cursor updated
	return				; and return

; Here to clear to EOF

clreof:	save hpos			; save current horizontal pos
	save vpos			; ditto for vertical
cleof1:	call clreol			; clear to end of line
	store %zeros,hpos		; now clear all of the lines below
	aos x,vpos			; bump to new line
	caxge x,nlines			; all done yet?
	 jrst cleof1			; nope, kill next line
	retr vpos			; get back old vertical position
	retr hpos			; and horizontal position
	return				; and return
; Line insert/delete

; Here to insert a line

inslin:	move a,x			; copy # of lines to hack
insln0:	move x,vpos			; load vertical position
	imulx x,nwrdln			; make into word counter
	addi x,screen			; address of first word of cursor line
	cain x,screen+<nlines-1>*nwrdln	; skip unless at bottom line
	 jrst insln2			; on bottom, zap it
	move y,[screen+<nlines-2>*nwrdln,,screen+<nlines-1>*nwrdln]
insln1:	move z,y			; copy pointer
	blt z,nwrdln-1(y)		; copy one line
	adjsp y,-nwrdln			; offset a line
	caie x,(y)			; done yet?
	 jrst insln1			; nope
insln2:	store ascii/     /+1,2(x)	; blanks
	movei y,nwrdln-2-1(x)		; number to do
	addx x,3			; address offset
	hrli x,-1(x)			; complete pointer
	blt x,(y)			; zak!
	sojg a,insln0			; loop for more lines
	store %fword,saupdp		; updated the world
	jrst ntisr1			; and return

; Here to delete a line

dellin:	move a,x			; copy # of lines to hack
delln0:	move x,vpos			; get vertical position
	imulx x,nwrdln			; frobs to do
	addi x,screen			; address of first word of cursor line
	cain x,screen+<nlines-1>*nwrdln	; at bottom line?
	 jrst delln1			; yup, just copy extra line in
	movei y,(x)			; make a copy
	addx y,nwrdln			; address of next line
	hrli x,(y)			; make a BLT pointer
	blt x,screen+<nlines-1>*nwrdln-1; copy the lines
delln1:	store ascii/     /+1,2(x)	; blanks
	movei y,nwrdln-2-1(x)		; number to do
	addx x,3			; address offset
	hrli x,-1(x)			; complete pointer
	blt x,(y)			; zak!
	sojg a,delln0			; loop for more lines
	store %fword,saupdp		; updated the world
	jrst ntisr1			; and return
; Character insert

inschr:	move c,a			; copy character counter
insch0:	move x,vpos			; get vertical position
	imulx x,nwrdln			; now number of words
	move a,x			; copy it for hacking
	addi a,screen+nwrdln+3		; address of last text word
	move y,hpos			; get horizontal position
	idivx y,5			; make it words
	addi x,screen+2(y)		; address of word with cursor
	ldb y,[010700,,(x)]		; first character in next word
	ldb b,[	103400,,(x)
		102500,,(x)
		101600,,(x)
		100700,,(x)
		100000,,(x)](z)
	dpb b,[	013400,,(x)
		012500,,(x)
		011600,,(x)
		010700,,(x)
		010000,,(x)](z)
	movx b,<" >			; space in hole
	dpb b,[	350700,,(x)
		260700,,(x)
		170700,,(x)
		100700,,(x)
		010700,,(x)](z)
	jrst insch1			; check for being done

; At each iteration Y has last character, X has next address

insch2:	move z,y			; copy the character
	ldb y,[010700,,(x)]		; first character in next word
	dpb z,[000700,,(x)]		; last character here
	move z,(x)			; get word being hacked
	rot z,-7			; put characters in right place
	iorx z,1			; make sure bit 1.1 is on
	movem z,(x)			; save character in word
insch1:	came x,a			; at last address?
	 aoja x,insch2			; nope
	store %fword,scupdp		; some update somewhere
	move x,vpos			; this line
	sojg c,insch0			; loop for more characters
	store %fword,slupdp(x)		; this line was hacked
	jrst ntisr1			; and return
; Character delete

delchr:	move c,x			; copy number of characters to hack
delch0:	move x,vpos			; get current vertical position
	imulx x,nwrdln			; number of words
	move a,x			; save it for later
	addi a,screen+nwrdln-3		; address of last text word in line
	move y,hpos			; get horizontal position
	idivx y,5			; number of words
	addi x,screen+2(y)		; address of word with cursor
	ldb b,[	013400,,(x)
		012500,,(x)
		011600,,(x)
		010700,,(x)
		010000,,(x)](z)
	dpb b,[	103400,,(x)
		102500,,(x)
		101600,,(x)
		100700,,(x)
		100000,,(x)](z)
	jrst delch1			; check for being done

; Each time around the iteration A had address of next word

delch2:	ldb y,[350700,,(x)]		; last character in previous
	dpb y,[010700,,-1(x)]		; to previous
	ldb y,[013400,,(x)]		; get last characters in this word
	dpb y,[103400,,(x)]		; put back left justified
delch1:	came x,a			; done?
	 aoja x,delch2			; not yet
	movx y,<" >			; get a space
	dpb y,[010700,,(x)]		; blank out last column
	store %fword,scupdp		; screen updated someplace
	move x,vpos			; get this line
	sojg c,delch0			; hack another character
	store %fword,slupdp(x)		; flag this line hacked
	jrst ntisr1			; and return
subttl Display update subroutines

scnupd:	skipe slowip			; in slow mode?
	 jrst scnup1			; yes, good enough
	movx x,<-nlines,,>		; load pointer to line update table
	movx y,%zeros			; initialize line count
	skipe slupdp(x)			; does this line need hacking?
	 addx y,1			; yup, bump count
	aobjn x,.-2			; try for more lines
	caxl y,nlnupd			; three lines or so?
	 store %fword,saupdp		; yup, must update screen
scnup1:	aose saupdp			; update entire screen?
	 jrst scupd1			; nope, maybe selective
	store %zeros,scupdp		; clear other update flags
	store %zeros,slupdp,slupdp+nlines-1; . . .
	ddupg sdisp			; output new screen

; Update cursor

csrupd:	call glnini			; clear cursor line
	skipge x,ovpos			; got an old position?
	 jrst .+3			; nope, don't try to clear old
	  call getcsy			; get cursor vertical position
	  ddupg cdisp			; clear cursor
	move x,hpos			; horizontal character position
	imulx x,6			; horizontal bit position
	addx x,2			; graphics mode hack
	idivx x,32.
	movns y
	movx z,(740000)
	lsh z,(y)
	ldb a,[010300,,z]
	rot a,-3
	andx z,777777777760
	iorx z,2
	iorx a,2
	movem z,scc+2(x)
	movem a,scc+3(x)
	move x,vpos			; get current vertical position
	movem x,ovpos			; save as old position
	call getcsy			; get cursor vertical position
	ddupg cdisp			; and send it all out
	return				; finally return

scupd1:	aose scupdp			; did any update happen?
	 jrst scupd2			; nope, try for just cursor
	movx x,<-nlines,,>		; load line pointer
scup1a:	skipe slupdp(x)			; need to hack this line?
	 call updlin			; yup
	aobjn x,scup1a			; loop for next line
	jrst csrupd			; now update cursor

scupd2:	aose crupdp			; was cursor hacked
	 return				; nope, just return
	jrst csrupd			; yes, then hack the cursor
; More display updating stuff

; Set up display program vertical position

getcsy:	imulx x,12.
	addx x,24.+10.
	dpb x,[140400,,scc+1]
	lsh x,-4
	dpb x,[240500,,scc+1]
	return				; and return

; Display a single line

updlin:	store %zeros,slupdp(x)		; am updating now
	hrrz y,x			; line number
	imulx y,nwrdln			; word position
	addi y,screen			; address of start of line
	hrrm y,ldisp			; hack up line display command
	movem y,ldisp+3			; . . .
	hrrz z,x			; get line number again
	imulx z,12.
	addx z,24.			; starting raster number
	move a,linprg			; program
	dpb z,[140400,,a]		; zap in low 4 bits of address
	lsh z,-4			; throw low bits away
	dpb z,[240500,,a]		; high 5 bits of address
	movem a,(y)			; save this command
	move linpr1			; go to column 2
	movem 1(y)			; save this command
	store %zeros,nwrdln-1(y)	; clear word at EOL
	ddupg ldisp			; display the line
	movx a,1			; nothingness
	movem a,(y)			; zap command
	movem a,1(y)			; . . .
	aos nwrdln-1(y)			; put back 5 nulls
	return				; now return

linprg:	ddcmd 1,46,4,0,5,0		; line update commands
linpr1:	ddcmd 3,2,3,2,3,2
subttl SUPDUP commands

cmdcmd:	inchrw x			; get command character
	caxe x,"s			; slow mode?
	 caxn x,"S			; . . .
	  jrst [store %fword,slowip	; yes
		outstr [asciz/Entering slow display mode!
/]
		jrst ttiser]		; and continue gobbling input
	caxe x,"f			; fast mode?
	 caxn x,"F			; . . .
	  jrst [store %zeros,slowip	; yes
		outstr [asciz/Entering fast display mode!
/]
		jrst ttiser]		; and continue hacking
	caxe x,"q			; quit?
	 caxn x,"Q			; . . .
	  jrst quit			; yup, instant suicide
	caxe x,"l			; logout foreign job?
	 caxn x,"L			; . . .
	  jrst killer			; it's a killer you know
	caxe x,"k			; kill foreign job first?
	 caxn x,"K			; . . .
killer:	  jrst [movx x,300		; escape code
		call netoc1		; prepare for escape
		movx x,301		; kill other job code
		call netoc1		; send it too
		call netsnd		; now send this command out
		outstr [asciz/Logged out foreign job and /]
		jrst quit]		; and die die die
	caxe x,"h			; help me?
	 caxn x,"H			; . . .
	  caxa				; yup
	   caxn x,"?			; yet another way to beg for help
	    jrst [	outstr hlptxt	; give user help text
			jrst @ppdisp]	; and show the page printer

; This command is only for me when debugging, so is not documented!!

	caxe x,"d			; enter DDT | RAID?
	 caxn x,"D			; . . .
	  jrst [skipn x,jobddt		; is there a DDT?
		 jrst [	outstr [asciz/No DDT!
/]
			jrst @youluz]	; sorry 'bout that
		call (x)		; enter DDT
		jrst ttiser]		; return from DDT, return to user
; More SUPDUP commands stuff

	caxe x,"p			; temporarily restore page printer?
	 caxn x,"P			; . . .
ppdisp:	  jrst [outstr [asciz/Type any character to get back to ITS:/]
		hrroi x,[004000,,400\"N]; <BREAK>N
		ttyset x,		; normalize screen
		hrroi x,[004000,,"W]	; <ESCAPE>W
		ttyset x,		; restore who-line
		movx x,1		; wait one second...
		sleep x,		; ... to let the dust settle
		hrroi x,[004000,,"P]	; <ESCAPE>P
		ttyset x,		; restore page printer
		inchrw x		; get a character
		clrbfi			; flush any other input (like CRLF)
		outstr [asciz/ [Continued]
/]					; pretty up page printer
		ppact 0			; flush PP 0
		leypos 2000		; line editor off screen
		ddupg sclear		; zap screen
		hrroi x,[004000,,"W]	; <ESCAPE>W
		ttyset x,		; restore who-line quickly
		store %fword,saupdp	; must redisplay whole screen
		call scnupd		; update screen
		store %zeros,ntiinp	; clear output resets
		jrst ttiser]		; all done
	ldb y,[001000,,x]		; get character plus [CONTROL]
	caxe y,%txctl\"z		; αz or αβz?
	 caxn y,%txctl\"Z		; αZ or αβZ?
	  jrst imgsnd			; yes, send it in image form
	caxe y,%txctl\"_		; α_ or αβ_?
youluz:	 jrst [	movx x,%fword		; to myself
		beep x,			; breedle!
		jrst ttiser]		; now continue
imgsnd:	store %fword,imgchp		; image characters now
	call netoch			; send it too
	call netsnd			; send it out
	jrst ttiser			; and try for another

hlptxt:	asciz/
SUPDUP Commands:

F	Use Fast display mode (default)
H	Type this cruft
K	Kill job at remote host, close connection
L	Same as K
P	Temporarily restore page printer; typing any character restores the
	 screen to ITS
Q	Detach job at remote host, close connection (quit)
S	Use Slow display mode
?	Same as H

αz, αβz, αZ, αβZ, α_, and αβ_ are sent as is to the foreign host after a
command instead of being mapped to forms of [CALL] or [BACK NEXT].  Any
other character is illegal and is flushed.

/
subttl Random routines, literals, etc.

; Here if could not get terminal name; give a random string

rndtid:	move y,[440700,,[asciz/Unknown Data Disc/]]
	burp [asciz/Unable to get the name of this Data Disc.
/]
sndid1:	ildb x,y			; get a character
	call netoc1			; send it
	jumpn x,sndid1			; and continue if not done
	jrst tidone			; all done

; Here to get a character from terminal rooms table

getch:	0				; return PC
	sosg dsibf+2			; buffer ready?
	 in dsk,			; no, get one then
	  caxa				; won
	   jrst rndtid			; lost, send random name
	ildb x,dsibf+1			; get a character
	jumpe x,getch+1			; flush nulls
	caxe x,↑M			; hit a terpri?
	 aos getch			; no, bump return PC
	jrst 2,@getch			; now return

; Die when we lose

diedie:	burp [asciz/Connection failed.
/]
	caxa				; different message
quit:	 outstr [asciz/Closed connection.
/]
	ddupg sclear			; clear user's screen
	reset				; restore the world
	hrroi x,[004000,,400\"N]	; <BREAK>N
	ttyset x,			; restore PP
	hrroi x,[004000,,"W]		; <ESCAPE>W
	ttyset x,			; restore who-line
	exit				; bye bye

; ICP lost

icpluz:	outstr [asciz/Failed/]
	exit				; bye bye

...lit:	variables			; must not have variables!
ifn .-...lit,.err Variables lose lose lose

	constants			; generate constants

	end SUPDUP